#include "StdAfx.h"
#include "QuoteBroadcast.h"
#include "BoradcastThread.h"
#include "PeerSocket.h"
#include "MuchInfo.h"
#include "Parser.h"
#include <Shlwapi.h>

CQuoteBroadcast::CQuoteBroadcast( HWND hWnd, UINT uMsg )
{
	m_pThread = NULL;
	try
	{
		m_pThread = AfxBeginThread( RUNTIME_CLASS(CBoradcastThread) );
		m_pThread->PostThreadMessage( CBoradcastThread::WM_SETHANDLER, (WPARAM)hWnd, (LPARAM)uMsg );
	}
	catch (std::exception& e)
	{
		CString strPrompt;
		strPrompt.Format( "%s", e.what() );
		AfxMessageBox( strPrompt );
	}
}

CQuoteBroadcast::~CQuoteBroadcast( void )
{
	Quitthread();
}

void CQuoteBroadcast::Quitthread( void )
{
	if( m_pThread != NULL )
	{
		m_pThread->ResumeThread();
		m_pThread->PostThreadMessage( WM_QUIT, 0, 0 );

		DWORD dwWait = ::WaitForSingleObject( m_pThread->m_hThread, 3*1000 );
		ASSERT( WAIT_OBJECT_0 == dwWait  || WAIT_FAILED == dwWait );
	}
}

bool CQuoteBroadcast::OpenPort( LPCTSTR strPort )
{
	if( NULL == m_pThread )
	{
		return false;
	}

	USHORT sPort = (USHORT)::StrToInt( strPort );
	//sPort = ::htons( (USHORT)sPort );
	m_pThread->PostThreadMessage( CBoradcastThread::WM_BIND, sPort, 0 );

	return true;
}

bool CQuoteBroadcast::Broadcast( BYTE* pBuffer, int nLen )
{
	if( NULL == m_pThread )
	{
		return false;
	}

	BYTE* pNewBuffer = new BYTE[nLen];
	::memcpy( pNewBuffer, pBuffer, nLen );
	m_pThread->PostThreadMessage( CBoradcastThread::WM_BROADCAST, (WPARAM)pNewBuffer, (LPARAM)nLen );

	return true;
}

//////////////////////////////////////////////////////////////////////////
CBroadcaster::CBroadcaster( UINT nID )
	: CQuoteSocket( nID )
	, m_apCodec(new MIEncoder)
	, m_nPackCount( 0 )
{	
	return ;
}

CBroadcaster::~CBroadcaster( void )
{
	ClearMap();
}

void CBroadcaster::RemovePeer( MAP_PEER::value_type& peer )
{
	peer.second->Close();
	delete peer.second;
}

bool CBroadcaster::Broadcast( BYTE* pBuffer, int nLen )
{
	if( NULL == m_apCodec.get() )
	{
		return false;
	}
	
	CParser parser( pBuffer, nLen );
	while( true )
	{
		int nNextLen = 0;
		const BYTE* pNext = parser.NextPack( nNextLen );
		if( NULL == pNext )
		{
			break;
		}

		const int MAX_PACK_LEN = 2000;
		BYTE pPack[MAX_PACK_LEN] = {0};
		int nPackLen = MAX_PACK_LEN;
		if( !m_apCodec->Codec( pNext, nNextLen, pPack, nPackLen ) )
		{
			return false;
		}

		Package pack( (BYTE*)pPack, nPackLen, false );
		if( !Broadcast( pack ) )
		{
			return false;
		}
	}

	return true;
}

bool CBroadcaster::Broadcast( const Package& pack )
{
	PostPackMsg( pack, ++m_nPackCount );

	MAP_PEER::iterator iter = m_mapSockets.begin();

	for( ; iter != m_mapSockets.end(); ++iter )
	{
		iter->second->Send( pack.m_pBuffer, pack.m_nBufLen );
	}

	return true;
}

void CBroadcaster::OnClose( int nErrorCode )
{
	CQuoteSocket::OnClose( nErrorCode );
}

void CBroadcaster::OnAccept( int nErrorCode )
{
	switch( nErrorCode )
	{
	case 0:
		{
			SOCKADDR_IN addr = {0};
			int nAddrLen = sizeof(addr);
			
			CPeerSocket* pPeer = new CPeerSocket( MakePeerID(), *this );
			pPeer->SetHandler( GetHandler(), WM_SOCKMSG );
			if( !Accept( *pPeer, (SOCKADDR*)(&addr), &nAddrLen ) )
			{
				delete pPeer;
				// PostFailedSockMsg( ISockMsg::SA_ACCEPT );
			}
			else
			{
				pPeer->SetAddrRemote( addr );
				m_mapSockets[pPeer->GetID()] = pPeer;
				// PostSucceedSockMsg( ISockMsg::SA_ACCEPT, addr );
			}

			break;
		}
	default :
		{
			PostFailedSockMsg( ISockMsg::SA_ACCEPT, SOCKADDR_IN(), nErrorCode );
			break;
		}
	}

	CQuoteSocket::OnAccept( nErrorCode );
}

void CBroadcaster::OnSend( int nErrorCode )
{
	CQuoteSocket::OnSend( nErrorCode );
}

void CBroadcaster::DeletePeer( CPeerSocket* peer )
{
	ASSERT( NULL != peer );

	MAP_PEER::iterator iter = m_mapSockets.find( peer->GetID() );
	if( iter != m_mapSockets.end() )
	{
		delete iter->second;
		m_mapSockets.erase( iter );
	}
}
